package com.weibopay.gf.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import com.weibopay.gf.support.ApiUrl;

import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * 签名工具
 */
public class SignUtils {

    private final String publicKey;
    private final String privateKey;

    private SignUtils(String publicKey, String privateKey) {
        this.publicKey = publicKey;
        this.privateKey = privateKey;
    }

    public static SignUtils init(String publicKey, String privateKey) {
        if (StrUtil.isBlank(publicKey) || StrUtil.isBlank(privateKey)) {
            throw new IllegalArgumentException("RSA key is blank");
        }
        return new SignUtils(publicKey, privateKey);
    }

    public static SignUtils init(String publicKey) {
        if (StrUtil.isBlank(publicKey)) {
            throw new IllegalArgumentException("RSA key is blank");
        }
        return new SignUtils(publicKey, null);
    }

    /**
     * 针对请求参数进行签名
     *
     * @param body 请求内容
     * @return 签名参数
     */
    public String sign(Map<String, Object> body) {
        //组装加签参数
        String signParam = MapUtil.sortJoin(body, "&", "=", true);
        //开始签名
        Sign sign = SecureUtil.sign(SignAlgorithm.SHA1withRSA, privateKey, publicKey);
        byte[] signByte = sign.sign(signParam.getBytes(StandardCharsets.UTF_8));
        //返回签名后的字符串
        return Base64.encode(signByte);
    }

    /**
     * 验证签名
     *
     * @param signMap 通知参数
     * @return 验证结果
     */
    public boolean verifySign(Map<String, Object> signMap) {
        String reqSign = (String) signMap.getOrDefault("sign", "");
        //过滤无需验签的参数
        CommonUtils.filter(signMap);
        //拼接参数用户校验签名
        String signParam = MapUtil.sortJoin(signMap, "&", "=", true);
        //自行加签
        Sign sign = SecureUtil.sign(SignAlgorithm.SHA1withRSA, privateKey, publicKey);
        //验签
        return sign.verify(signParam.getBytes(StandardCharsets.UTF_8), Base64.decode(reqSign));
    }
}
